#pragma once 

#include <commdlg.h>
#include <string>
#include <GL/glut.h>
#include <tchar.h>

using namespace std;

namespace dalelib
{

LPCWSTR class_name = _T("Win32Window");
LPCWSTR title = _T("Win32Window");

class Win32Window
{
private:

	string _name;
	int _pos_x;
	int _pos_y;
	int _width;
	int _height;

	HDC _hDC;
	HGLRC _hRC;
	HINSTANCE _hInstance;
	bool _keys[256];
	bool _active;
	static Win32Window* windowinstance; // dirty hack to have non-static wndproc

public:

	HWND _hWnd;

	Win32Window()
		: _active(true)
	{ 
		setPos(0,0); 
		setSize(256,256); 
		setName("Win32Window"); 
	}

	void setName(const string _Name) { _name = _Name; }

	void setPos(const int _Pos_x, const int _Pos_y) 
	{ 
		_pos_x = _Pos_x; 
		_pos_y = _Pos_y; 
	}
	
	void setSize(const int _Size_x, const int _Size_y) 
	{ 
		_width = _Size_x; 
		_height = _Size_y; 
	}

	virtual void resize(const int _Width, const int _Height) = 0;
	virtual void setup() = 0;
	virtual void setdown() = 0;
	virtual void update() = 0;
	virtual void draw() = 0;

	bool init()
	{
		int bits = 32;
		_hInstance = GetModuleHandle(NULL);

		RECT		WindowRect;
		WindowRect.left = (long)0;
		WindowRect.right = (long)_width;
		WindowRect.top = (long)0;
		WindowRect.bottom = (long)_height;

		WNDCLASS wc;
//		memset( &wc, 0, sizeof(wc) );
//		wc.cbSize			= sizeof(wc);
		wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
		wc.lpfnWndProc		= (WNDPROC)staticWndProc;
		wc.cbClsExtra		= 0;
		wc.cbWndExtra		= 0;
		wc.hInstance		= _hInstance;
		wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);
//		wc.hIconSm			= wc.hIcon;
		wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
		wc.hbrBackground	= NULL;
		wc.lpszMenuName		= MAKEINTRESOURCE(IDR_MENU); ;
		wc.lpszClassName	= class_name;
		if( !RegisterClass( &wc ) ) return false;

		DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
		DWORD dwStyle = WS_OVERLAPPEDWINDOW;

		AdjustWindowRectEx( &WindowRect, dwStyle, false, dwExStyle );

		if( !(_hWnd = CreateWindowEx(	dwExStyle, class_name, title, dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
										_pos_x, _pos_y, _width, _height,
										NULL, NULL, _hInstance, NULL ) ) )
		{
			killGLWindow();
			MessageBoxA( NULL, "Window Creation Error.","ERROR", MB_OK | MB_ICONEXCLAMATION );
			return FALSE;
		}


		static	PIXELFORMATDESCRIPTOR pfd =
		{
			sizeof(PIXELFORMATDESCRIPTOR),
			1,
			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
			PFD_TYPE_RGBA,
			bits,
			0, 0, 0, 0, 0, 0,
			0,
			0,
			0,
			0, 0, 0, 0,
			16,
			0,
			0,
			PFD_MAIN_PLANE,
			0,
			0, 0, 0
		};
		
		_hDC = GetDC(_hWnd);
		GLuint pf = ChoosePixelFormat( _hDC, &pfd );
		SetPixelFormat( _hDC, pf, &pfd );
		_hRC = wglCreateContext( _hDC );
		wglMakeCurrent( _hDC, _hRC );

		ShowWindow( _hWnd, SW_SHOW );
		SetForegroundWindow( _hWnd );
		SetFocus( _hWnd );
		resize( _width-8, _height-54 ); // account for border
		setup();

		windowinstance = this; // this has to be set AFTER createwindow

		return TRUE;
	}

	static LRESULT CALLBACK staticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
	{
		if( windowinstance ) 
			return windowinstance->wndProc( uMsg, wParam, lParam );
		else
			return DefWindowProc( hWnd, uMsg, wParam, lParam );
	}


	LRESULT wndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		switch (uMsg)
		{
			case WM_ACTIVATE: if (!HIWORD(wParam)) _active = true; else _active = false; break;
			case WM_SYSCOMMAND:
				switch (wParam)
				{
					case SC_SCREENSAVE:
					case SC_MONITORPOWER:
					return 0;
				}
				break;
//			case WM_COMMAND: respondToMenuCommand(LOWORD(wParam)); break; 
			case WM_CLOSE: PostQuitMessage(0); break;
			case WM_KEYDOWN: _keys[wParam] = true; break;
			case WM_KEYUP: _keys[wParam] = false; break;
			case WM_SIZE: resize(LOWORD(lParam),HIWORD(lParam)); break;
			default: DefWindowProc( _hWnd, uMsg, wParam, lParam );
		}
		return 0;
	}

	void killGLWindow()
	{
		wglMakeCurrent( NULL, NULL );
		if( _hRC ) { wglDeleteContext( _hRC ); _hRC = NULL; }
		if( _hDC ) { ReleaseDC( _hWnd, _hDC ); _hDC = NULL; }
		if( _hWnd ) { DestroyWindow( _hWnd ); _hWnd = NULL; }
		if( _hInstance ) { UnregisterClass( class_name, _hInstance ); _hInstance = NULL; }
	}

	void run()
	{
		MSG msg;
		bool done = false;

		while( !done )
		{
			if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
			{
				if( msg.message == WM_QUIT ) done = true;
				else
				{
					TranslateMessage( &msg );
					DispatchMessage( &msg );
				}
			}
			else
			{
				if( _active )
				{
					if( _keys[VK_ESCAPE] ) done = TRUE;
					else
					{
						update();
						draw();
						SwapBuffers( _hDC );
					}
				}
			}
		}

		killGLWindow();
//		return (msg.wParam);

	}


};

Win32Window* Win32Window::windowinstance = 0;

} // namespace dalelib


/*
void respondToMenuCommand(int cmd)
{
	OPENFILENAME ofn; // open/save file dialog box
	std::string file = "hello";
	char szFile[260];
	
	switch(cmd) 
	{ 
		case IDM_FILE_NEW: 
			agent->reset(); 
			break; 
 
		case IDM_FILE_OPEN:
			ZeroMemory(&ofn, sizeof(ofn));
			ofn.lStructSize = sizeof(ofn);
			ofn.hInstance = hInstance;
			ofn.hwndOwner = hWnd;
			ofn.lpstrFile = szFile;
			ofn.lpstrFile[0] = '\0';
			ofn.nMaxFile = sizeof(szFile);
			ofn.lpstrFilter = "Text\0*.txt\0All\0*.*\0";
			ofn.lpstrDefExt = ".txt";
			ofn.nFilterIndex = 1;
			ofn.lpstrTitle = "Open robot";
			ofn.lpstrFileTitle = NULL;
			ofn.nMaxFileTitle = 0;
			ofn.lpstrInitialDir = NULL;
			ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXTENSIONDIFFERENT;
			if(GetOpenFileName(&ofn)) agent->load(szFile); 
			break; 

		case IDM_FILE_SAVE: 
			ZeroMemory(&ofn, sizeof(ofn));
			ofn.lStructSize = sizeof(ofn);
			ofn.hInstance = hInstance;
			ofn.hwndOwner = hWnd;
			ofn.lpstrFile = szFile;
			ofn.lpstrFile[0] = '\0';
			ofn.nMaxFile = sizeof(szFile);
			ofn.lpstrFilter = "Text\0*.txt\0All\0*.*\0";
			ofn.lpstrDefExt = ".txt";
			ofn.nFilterIndex = 1;
			ofn.lpstrTitle = "Save robot";
			ofn.lpstrFileTitle = NULL;
			ofn.nMaxFileTitle = 0;
			ofn.lpstrInitialDir = NULL;
			ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXTENSIONDIFFERENT;
			if(GetSaveFileName(&ofn)) agent->save(szFile); 
			break; 

		case IDM_VIEW_FULLSCREEN:
			killGLWindow();
			fullscreen=!fullscreen;
			CreateGLWindow(window_name,800,600,16,fullscreen);
			break;
			
		case IDM_VIEW_AGENT: DISPLAY_MODE = 0; break;

		case IDM_VIEW_BIRDSEYE: DISPLAY_MODE = 1; break;
		 
		case IDM_VIEW_BRAIN: DISPLAY_MODE = 2; break; 
		
		case IDM_VIEW_GRAPHS: DISPLAY_MODE = 3; break; 
			
		default: 
			break; 
	} 
}
*/
